#include <stdlib.h>

#include "../include/Arbre.h"
#include "../include/Symbole.h"
#include "../include/SymboleValue.h"

// NoeudSeqInst

NoeudSeqInst::NoeudSeqInst() : m_tabInst()
{
}

int NoeudSeqInst::getValeur()
{
    int valeur = 0;
    for(unsigned int i = 0; i < this->m_tabInst.size(); i++)
    {
        valeur = this->m_tabInst[i]->getValeur();    // on evalue chaque instruction de la séquence
    }
    return valeur; // par convention, resultat = valeur de la derniere instruction
}

void NoeudSeqInst::afficher(unsigned short indentation)
{
    Noeud::afficher(indentation);
    cout << "Noeud - Sequence de " << this->m_tabInst.size() << " instruction(s)" << endl;
    for(unsigned int i = 0; i < this->m_tabInst.size(); i++)
    {
        this->m_tabInst[i]->afficher(indentation + 1);       // on affiche les fils en augmentant l'indentation
    }
}

void NoeudSeqInst::ajouteInstruction(Noeud* instruction)
{
    this->m_tabInst.push_back(instruction);
}

// NoeudAffectation

NoeudAffectation::NoeudAffectation(Noeud* variable, Noeud* expression)
{
    this->m_variable = variable;
    this->m_expression = expression;
}

int NoeudAffectation::getValeur()
{
    int valeur = this->m_expression->getValeur(); // on évalue l'expression
    ((SymboleValue*) this->m_variable)->setValeur(valeur);        // on affecte la variable
    return valeur; // par convention, une affectation a pour valeur la valeur affectée
}

void NoeudAffectation::afficher(unsigned short indentation)
{
    Noeud::afficher(indentation);
    cout << "Noeud - Affectation" << endl;
    this->m_variable->afficher(indentation + 1);    // on affiche variable et expression
    this->m_expression->afficher(indentation + 1);    // en augmentant l'indentation
}

// NoeudOperateurBinaire

NoeudOperateurBinaire::NoeudOperateurBinaire(Symbole operateur, Noeud* operandeGauche, Noeud* operandeDroit)
{
    this->m_operateur = operateur;
    this->m_operandeGauche = operandeGauche;
    this->m_operandeDroit = operandeDroit;
}

int NoeudOperateurBinaire::getValeur()
{
    int valeur = 0;
    int og = this->m_operandeGauche->getValeur();
    int od = this->m_operandeDroit->getValeur();
    if(this->m_operateur == "+")
    {
        valeur = og + od;
    }
    else if(this->m_operateur == "-")
    {
        valeur = og - od;
    }
    else if(this->m_operateur == "*")
    {
        valeur = og * od;
    }
    else   // this->operateur == "/"
        if(od != 0)
        {
            valeur = og / od;
        }
        else
        {
            cout << "Erreur pendant l'interpretation : division par zero" << endl;
            exit(0);    // plus tard on levera une exception
        }
    return valeur;
}

void NoeudOperateurBinaire::afficher(unsigned short indentation)
{
    Noeud::afficher(indentation);
    cout << "Noeud - Operateur Binaire \"" << this->m_operateur.getChaine() << "\" applique a : " << endl;
    this->m_operandeGauche->afficher(indentation + 1);    // on affiche fils gauche et fils droit
    this->m_operandeDroit->afficher(indentation + 1);    // en augmentant l'indentation
}
